using Microsoft.Xna.Framework.Input.Touch;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
namespace Microsoft.Phone.Controls
{
	public class GestureListener
	{
		private static DispatcherTimer _timer;
		private static bool _isInTouch;
		private static List<UIElement> _elements;
		private static Point _gestureOrigin;
		private static bool _gestureOriginChanged;
		private static Orientation? _gestureOrientation;
		private static Point _cumulativeDelta;
		private static Point _cumulativeDelta2;
		private static Point _finalVelocity;
		private static Point _pinchOrigin;
		private static Point _pinchOrigin2;
		private static Point _lastSamplePosition;
		private static Point _lastSamplePosition2;
		private static bool _isPinching;
		private static bool _flicked;
		private static bool _isDragging;
		public event EventHandler<GestureEventArgs> GestureBegin;
		public event EventHandler<GestureEventArgs> GestureCompleted;
		public event EventHandler<GestureEventArgs> Tap;
		public event EventHandler<GestureEventArgs> DoubleTap;
		public event EventHandler<GestureEventArgs> Hold;
		public event EventHandler<DragStartedGestureEventArgs> DragStarted;
		public event EventHandler<DragDeltaGestureEventArgs> DragDelta;
		public event EventHandler<DragCompletedGestureEventArgs> DragCompleted;
		public event EventHandler<FlickGestureEventArgs> Flick;
		public event EventHandler<PinchStartedGestureEventArgs> PinchStarted;
		public event EventHandler<PinchGestureEventArgs> PinchDelta;
		public event EventHandler<PinchGestureEventArgs> PinchCompleted;
		static GestureListener()
		{
			Touch.add_FrameReported(new TouchFrameEventHandler(GestureListener.OnTouchFrameReported));
			TouchPanel.set_EnabledGestures(999);
			DispatcherTimer dispatcherTimer = new DispatcherTimer();
			dispatcherTimer.set_Interval(TimeSpan.FromMilliseconds(100.0));
			GestureListener._timer = dispatcherTimer;
			GestureListener._timer.add_Tick(new EventHandler(GestureListener.OnTimerTick));
		}
		private static void OnTouchFrameReported(object sender, TouchFrameEventArgs e)
		{
			bool flag = false;
			Point position = new Point(0.0, 0.0);
			using (IEnumerator<TouchPoint> enumerator = e.GetTouchPoints(null).GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					TouchPoint current = enumerator.get_Current();
					if (current.get_Action() != 3)
					{
						position = current.get_Position();
						flag = true;
						break;
					}
				}
			}
			if (!GestureListener._isInTouch && flag)
			{
				GestureListener._gestureOrigin = position;
				GestureListener.TouchStart();
			}
			else
			{
				if (GestureListener._isInTouch && !flag)
				{
					GestureListener.TouchComplete();
				}
				else
				{
					if (GestureListener._isInTouch)
					{
						GestureListener.TouchDelta();
					}
					else
					{
						GestureListener.TouchStart();
					}
				}
			}
			GestureListener._isInTouch = flag;
		}
		private static void TouchStart()
		{
			double num;
			GestureListener._cumulativeDelta2.set_Y(num = 0.0);
			double num2;
			GestureListener._cumulativeDelta2.set_X(num2 = num);
			double x;
			GestureListener._cumulativeDelta.set_Y(x = num2);
			GestureListener._cumulativeDelta.set_X(x);
			double x2;
			GestureListener._finalVelocity.set_Y(x2 = 0.0);
			GestureListener._finalVelocity.set_X(x2);
			GestureListener._isDragging = (GestureListener._flicked = false);
			GestureListener._elements = new List<UIElement>(VisualTreeHelper.FindElementsInHostCoordinates(GestureListener._gestureOrigin, Application.get_Current().get_RootVisual()));
			GestureListener._gestureOriginChanged = false;
			GestureListener.RaiseGestureEvent<GestureEventArgs>((GestureListener helper) => helper.GestureBegin, () => new GestureEventArgs(GestureListener._gestureOrigin, GestureListener._gestureOrigin), false);
			GestureListener.ProcessTouchPanelEvents();
			GestureListener._timer.Start();
		}
		private static void TouchDelta()
		{
			GestureListener.ProcessTouchPanelEvents();
		}
		private static void TouchComplete()
		{
			GestureListener.ProcessTouchPanelEvents();
			GestureListener.RaiseGestureEvent<GestureEventArgs>((GestureListener helper) => helper.GestureCompleted, () => new GestureEventArgs(GestureListener._gestureOrigin, GestureListener._lastSamplePosition), false);
			GestureListener._elements = null;
			GestureListener._gestureOrientation = default(Orientation?);
			GestureListener._timer.Stop();
		}
		private static void OnTimerTick(object sender, EventArgs e)
		{
			GestureListener.ProcessTouchPanelEvents();
		}
		private static void ProcessTouchPanelEvents()
		{
			GestureListener.<>c__DisplayClass2f <>c__DisplayClass2f = new GestureListener.<>c__DisplayClass2f();
			<>c__DisplayClass2f.delta = new Point(0.0, 0.0);
			GeneralTransform generalTransform = null;
			while (TouchPanel.get_IsGestureAvailable())
			{
				GestureSample gestureSample = TouchPanel.ReadGesture();
				Point samplePosition = gestureSample.get_Position().ToPoint();
				Point samplePosition2 = gestureSample.get_Position2().ToPoint();
				Point sampleDelta = gestureSample.get_Delta().ToPoint();
				GestureListener.GetTranslatedDelta(ref generalTransform, ref sampleDelta, ref GestureListener._cumulativeDelta, gestureSample.get_GestureType() != 128);
				Point point = gestureSample.get_Delta2().ToPoint();
				GestureListener.GetTranslatedDelta(ref generalTransform, ref point, ref GestureListener._cumulativeDelta2, gestureSample.get_GestureType() != 128);
				if (GestureListener._elements == null || GestureListener._gestureOriginChanged)
				{
					GestureListener._gestureOrigin = samplePosition;
					GestureListener._elements = new List<UIElement>(VisualTreeHelper.FindElementsInHostCoordinates(GestureListener._gestureOrigin, Application.get_Current().get_RootVisual()));
					GestureListener._gestureOriginChanged = false;
				}
				if (!GestureListener._gestureOrientation.get_HasValue() && (sampleDelta.get_X() != 0.0 || sampleDelta.get_Y() != 0.0))
				{
					GestureListener._gestureOrientation = new Orientation?((Math.Abs(sampleDelta.get_X()) >= Math.Abs(sampleDelta.get_Y())) ? 1 : 0);
				}
				GestureType gestureType = gestureSample.get_GestureType();
				if (gestureType <= 64)
				{
					switch (gestureType)
					{
					case 1:
						GestureListener.RaiseGestureEvent<GestureEventArgs>((GestureListener helper) => helper.Tap, () => new GestureEventArgs(GestureListener._gestureOrigin, samplePosition), false);
						break;
					case 2:
						GestureListener.RaiseGestureEvent<GestureEventArgs>((GestureListener helper) => helper.DoubleTap, () => new GestureEventArgs(GestureListener._gestureOrigin, samplePosition), false);
						break;
					case 3:
						break;
					case 4:
						GestureListener.RaiseGestureEvent<GestureEventArgs>((GestureListener helper) => helper.Hold, () => new GestureEventArgs(GestureListener._gestureOrigin, samplePosition), false);
						break;
					default:
						if (gestureType != 32)
						{
							if (gestureType == 64)
							{
								if (!GestureListener._isPinching)
								{
									GestureListener._isPinching = true;
									GestureListener._pinchOrigin = samplePosition;
									GestureListener._pinchOrigin2 = samplePosition2;
									GestureListener.RaiseGestureEvent<PinchStartedGestureEventArgs>((GestureListener helper) => helper.PinchStarted, () => new PinchStartedGestureEventArgs(GestureListener._pinchOrigin, GestureListener._pinchOrigin2, GestureListener._pinchOrigin, GestureListener._pinchOrigin2), true);
								}
								GestureListener._lastSamplePosition = samplePosition;
								GestureListener._lastSamplePosition2 = samplePosition2;
								GestureListener.RaiseGestureEvent<PinchGestureEventArgs>((GestureListener helper) => helper.PinchDelta, () => new PinchGestureEventArgs(GestureListener._pinchOrigin, GestureListener._pinchOrigin2, samplePosition, samplePosition2), false);
							}
						}
						else
						{
							if (sampleDelta.get_X() != 0.0 || sampleDelta.get_Y() != 0.0)
							{
								if (!GestureListener._isDragging)
								{
									GestureListener.RaiseGestureEvent<DragStartedGestureEventArgs>((GestureListener helper) => helper.DragStarted, () => new DragStartedGestureEventArgs(GestureListener._gestureOrigin, GestureListener._gestureOrientation.get_Value()), true);
									GestureListener._isDragging = true;
								}
								GestureListener.<>c__DisplayClass2f expr_30C_cp_0 = <>c__DisplayClass2f;
								expr_30C_cp_0.delta.set_X(expr_30C_cp_0.delta.get_X() + sampleDelta.get_X());
								GestureListener.<>c__DisplayClass2f expr_32B_cp_0 = <>c__DisplayClass2f;
								expr_32B_cp_0.delta.set_Y(expr_32B_cp_0.delta.get_Y() + sampleDelta.get_Y());
								GestureListener._lastSamplePosition = samplePosition;
							}
						}
						break;
					}
				}
				else
				{
					if (gestureType != 128)
					{
						if (gestureType != 256)
						{
							if (gestureType == 512)
							{
								GestureListener._isPinching = false;
								GestureListener.RaiseGestureEvent<PinchGestureEventArgs>((GestureListener helper) => helper.PinchCompleted, () => new PinchGestureEventArgs(GestureListener._pinchOrigin, GestureListener._pinchOrigin2, GestureListener._lastSamplePosition, GestureListener._lastSamplePosition2), false);
								double num;
								GestureListener._cumulativeDelta2.set_Y(num = 0.0);
								double num2;
								GestureListener._cumulativeDelta2.set_X(num2 = num);
								double x;
								GestureListener._cumulativeDelta.set_Y(x = num2);
								GestureListener._cumulativeDelta.set_X(x);
								GestureListener._gestureOriginChanged = true;
							}
						}
						else
						{
							if (!GestureListener._flicked && (<>c__DisplayClass2f.delta.get_X() != 0.0 || <>c__DisplayClass2f.delta.get_Y() != 0.0))
							{
								GestureListener.RaiseGestureEvent<DragDeltaGestureEventArgs>((GestureListener helper) => helper.DragDelta, () => new DragDeltaGestureEventArgs(GestureListener._gestureOrigin, samplePosition, <>c__DisplayClass2f.delta, GestureListener._gestureOrientation.get_Value()), false);
								GestureListener.<>c__DisplayClass2f arg_550_0_cp_0 = <>c__DisplayClass2f;
								double x2;
								<>c__DisplayClass2f.delta.set_Y(x2 = 0.0);
								arg_550_0_cp_0.delta.set_X(x2);
							}
							if (GestureListener._isDragging)
							{
								GestureListener.RaiseGestureEvent<DragCompletedGestureEventArgs>((GestureListener helper) => helper.DragCompleted, () => new DragCompletedGestureEventArgs(GestureListener._gestureOrigin, GestureListener._lastSamplePosition, GestureListener._cumulativeDelta, GestureListener._gestureOrientation.get_Value(), GestureListener._finalVelocity), false);
								GestureListener.<>c__DisplayClass2f arg_5BD_0_cp_0 = <>c__DisplayClass2f;
								double x3;
								<>c__DisplayClass2f.delta.set_Y(x3 = 0.0);
								arg_5BD_0_cp_0.delta.set_X(x3);
							}
							double x4;
							GestureListener._cumulativeDelta.set_Y(x4 = 0.0);
							GestureListener._cumulativeDelta.set_X(x4);
							GestureListener._flicked = (GestureListener._isDragging = false);
							GestureListener._gestureOriginChanged = true;
						}
					}
					else
					{
						GestureListener._flicked = true;
						GestureListener._finalVelocity = sampleDelta;
						GestureListener.RaiseGestureEvent<FlickGestureEventArgs>((GestureListener helper) => helper.Flick, () => new FlickGestureEventArgs(GestureListener._gestureOrigin, sampleDelta), true);
					}
				}
			}
			if (!GestureListener._flicked && (<>c__DisplayClass2f.delta.get_X() != 0.0 || <>c__DisplayClass2f.delta.get_Y() != 0.0))
			{
				GestureListener.RaiseGestureEvent<DragDeltaGestureEventArgs>((GestureListener helper) => helper.DragDelta, () => new DragDeltaGestureEventArgs(GestureListener._gestureOrigin, GestureListener._lastSamplePosition, <>c__DisplayClass2f.delta, GestureListener._gestureOrientation.get_Value()), false);
			}
		}
		private static void GetTranslatedDelta(ref GeneralTransform deltaTransform, ref Point sampleDelta, ref Point cumulativeDelta, bool addToCumulative)
		{
			if (sampleDelta.get_X() != 0.0 || sampleDelta.get_Y() != 0.0)
			{
				if (deltaTransform == null && Application.get_Current().get_RootVisual() != null)
				{
					deltaTransform = GestureListener.GetInverseRootTransformNoOffset();
				}
				if (deltaTransform != null)
				{
					sampleDelta = deltaTransform.Transform(sampleDelta);
					if (addToCumulative)
					{
						cumulativeDelta.set_X(cumulativeDelta.get_X() + sampleDelta.get_X());
						cumulativeDelta.set_Y(cumulativeDelta.get_Y() + sampleDelta.get_Y());
					}
				}
			}
		}
		private static GeneralTransform GetInverseRootTransformNoOffset()
		{
			GeneralTransform inverse = Application.get_Current().get_RootVisual().TransformToVisual(null).get_Inverse();
			MatrixTransform matrixTransform = inverse as MatrixTransform;
			if (matrixTransform != null)
			{
				Matrix matrix = matrixTransform.get_Matrix();
				double offsetX;
				matrix.set_OffsetY(offsetX = 0.0);
				matrix.set_OffsetX(offsetX);
				matrixTransform.set_Matrix(matrix);
			}
			return inverse;
		}
		private static void RaiseGestureEvent<T>(Func<GestureListener, EventHandler<T>> eventGetter, Func<T> argsGetter, bool releaseMouseCapture) where T : GestureEventArgs
		{
			T args = default(T);
			FrameworkElement originalSource = null;
			bool flag = false;
			using (List<UIElement>.Enumerator enumerator = GestureListener._elements.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					FrameworkElement frameworkElement = (FrameworkElement)enumerator.get_Current();
					if (releaseMouseCapture)
					{
						frameworkElement.ReleaseMouseCapture();
					}
					if (!flag)
					{
						if (originalSource == null)
						{
							originalSource = frameworkElement;
						}
						GestureListener gestureListenerInternal = GestureService.GetGestureListenerInternal(frameworkElement, false);
						if (gestureListenerInternal != null)
						{
							SafeRaise.Raise<T>(eventGetter.Invoke(gestureListenerInternal), frameworkElement, delegate
							{
								if (args == null)
								{
									args = argsGetter.Invoke();
									args.OriginalSource = originalSource;
								}
								return args;
							});
						}
						if (args != null && args.Handled)
						{
							flag = true;
						}
					}
				}
			}
		}
	}
}
